package spring.boot.server.handler.auth;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTVerificationException;
import io.netty.channel.Channel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import spring.boot.server.codec.Invocation;
import spring.boot.server.common.NettyServerConstant;
import spring.boot.server.dispatcher.MessageHandler;
import spring.boot.server.message.auth.AuthRequest;
import spring.boot.server.message.auth.AuthResponse;
import spring.boot.server.server.NettyChannelManager;

@Slf4j
@Component
public class AuthRequestHandler implements MessageHandler<AuthRequest> {

    @Autowired
    private NettyChannelManager nettyChannelManager;

    @Override
    public void execute(Channel channel, AuthRequest authRequest) {
        // 如果未传递 accessToken
        if (StringUtils.isEmpty(authRequest.getAccessToken())) {
            AuthResponse authResponse = new AuthResponse();
            authResponse.setCode(101);
            authResponse.setMessage("认证 accessToken 未传入");
            channel.writeAndFlush(new Invocation(AuthResponse.TYPE, authResponse));
            return;
        }

        // 解析accessToken
        String accessToken = authRequest.getAccessToken();
        Long userId = null;
        try {
            userId = Long.parseLong(JWT.decode(accessToken).getAudience().get(0));
            log.info("Netty服务端解析accessToken成功,userId=[{}]", userId);
        } catch (Throwable e) {
            log.error("Netty服务端解析accessToken失败,errorMsg=[{}]", e.getMessage(), e);
        }
        if (userId == null) {
            AuthResponse authResponse = new AuthResponse();
            authResponse.setCode(102);
            authResponse.setMessage("从 accessToken 获取userId失败");
            channel.writeAndFlush(new Invocation(AuthResponse.TYPE, authResponse));
            return;
        }

        JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(NettyServerConstant.TOKEN_SECRET)).build();

        try {
            jwtVerifier.verify(accessToken);
            log.info("Netty服务端解析accessToken成功,并且未过期，userId=[{}]", userId);
        } catch (JWTVerificationException e) {
            log.error("accessToken错误或者过期，userId=[{}],errorMsg={}", userId, e.getMessage(), e);
            AuthResponse authResponse = new AuthResponse();
            authResponse.setCode(103);
            authResponse.setMessage("accessToken错误或者过期");
            channel.writeAndFlush(new Invocation(AuthResponse.TYPE, authResponse));
            return;
        }

        // 将用户和 Channel 绑定
        // 考虑到代码简化，我们先直接使用 accessToken 作为 User
        nettyChannelManager.addUser(channel, String.valueOf(userId));

        // 响应认证成功
        AuthResponse authResponse = new AuthResponse();
        authResponse.setCode(0);
        authResponse.setMessage("SUCCESS");
        channel.writeAndFlush(new Invocation(AuthResponse.TYPE, authResponse));
    }

    @Override
    public String getType() {
        return AuthRequest.TYPE;
    }

}
